package com.gs.tests.seleniumextjs;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.safari.SafariDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumWebDriver {
	public enum Browsers {Firefox, Chrome, InternetExplorer, Safari};
	public enum Locators {xpath, id, name, classname, paritallinktext, linktext, tagname};	
	private WebDriver	driver;
	private String appURL;
	//private String appBrowser;
	
	public SeleniumWebDriver(Browsers browser, String URL) throws Exception {
		appURL = URL;
		//appBrowser = browser.toString();
		
		switch (browser) {
			case Firefox:			{driver = new FirefoxDriver(); break;}
			case Chrome:			{driver = new ChromeDriver(); break;}
			case InternetExplorer:	{driver = new InternetExplorerDriver(); break;}
			case Safari:			{driver = new SafariDriver(); break;}
			default: 				{throw new Exception();}
		}				
	}
	
	public SeleniumWebDriver(String browser, String URL) throws Exception {
		appURL = URL;
		//appBrowser = browser.toString();
		
		switch (browser.toLowerCase()) {
			case "firefox":				{driver = new FirefoxDriver(); break;}
			case "chrome":				{driver = new ChromeDriver(); break;}
			case "internet explorer":	{driver = new InternetExplorerDriver(); break;}
			case "safari":				{driver = new SafariDriver(); break;}
			default: 					{throw new Exception();}
		}		
	}
	
	public void launch() {
		driver.get(appURL);
	}
		
	public void close() {
		driver.quit();
	}
	
	public WebDriver getDriver() {
		return driver;
	}
	
	/////////////////////////////////////////
	//waiting functionality
	/////////////////////////////////////////

	public void wait(int seconds) throws InterruptedException {
		Thread.sleep(seconds*1000);
	}
	
	public void wait(double seconds) throws InterruptedException {
		Thread.sleep(Double.doubleToLongBits(seconds*1000));
	}
	
	public void waitForElementDisplayed(Locators locator, String element) throws Exception {
		waitForElementDisplayed(getWebElement(locator, element), 5);
	}
	
	public void waitForElementDisplayed(Locators locator, String element, int seconds) throws Exception {
		waitForElementDisplayed(getWebElement(locator, element), seconds);
	}
	
	public void waitForElementDisplayed(WebElement element) throws Exception {
		waitForElementDisplayed(element, 5);
	}
	
	public void waitForElementDisplayed(WebElement element, int seconds) throws Exception {
		//wait for up to XX seconds for our error message
		long end = System.currentTimeMillis() + ( seconds * 1000 );
		
		while (System.currentTimeMillis() < end) {
			// If results have been returned, the results are displayed in a drop down.
			if (element.isDisplayed()) {
				break;
			}
		}
	}
	
	public void waitForPageLoaded(int seconds, final String pagetitle) {
		// check current page is loaded in seconds
		// and verify its title
		(new WebDriverWait(driver, seconds)).until(
			new ExpectedCondition<Boolean>() {
			    public Boolean apply(WebDriver d) {
			        return d.getTitle().equals(pagetitle);
			    }
			});
	}
	
	//////////////////////////////////////
	//checking element functionality
	//////////////////////////////////////
	
	//a method for checking id an element is displayed
	public void checkElementDisplayed(Locators locator, String element) throws Exception {
		checkElementDisplayed(getWebElement(locator, element));
	}
	
	public void checkElementDisplayed(WebElement element) throws Exception {
		//assertTrue(element.isDisplayed());
	}
	
	/////////////////////////////////////
	//selenium actions functionality
	/////////////////////////////////////
	
	//our generic selenium click functionality implemented
	public void click(Locators locator, String element) throws Exception {
		click(getWebElement(locator, element));
	}
	
	public void click(WebElement element) {
		Actions selAction = new Actions(driver);
		selAction.click(element).perform();
	}
	
	//a method to simulate the mouse hovering over an element
	public void hover(Locators locator, String element) throws Exception {
		hover(getWebElement(locator, element));
	}
	
	public void hover(WebElement element) throws Exception {
		Actions selAction = new Actions(driver);
		selAction.moveToElement(element).perform();
	}
	
	//our generic selenium type functionality
	public void type(Locators locator, String element, String text) throws Exception {
		type(getWebElement(locator, element), text);
	}
	
	public void type(WebElement element, String text) {
		Actions selAction = new Actions(driver);
		selAction.sendKeys(element, text).perform();
	}
	
	////////////////////////////////////
	//extra base selenium functionality
	////////////////////////////////////
	
	//a method to grab the web element using selenium webdriver
	public WebElement getWebElement(Locators locator, String element) throws Exception {
		
		By byElement;
		
		switch ( locator ) {		//determine which locator item we are interested in
			case xpath:		{byElement = By.xpath(element);	break;}
			case id:		{byElement = By.id(element); break;}
			case name:		{byElement = By.name(element); break;}
			case classname:		{byElement = By.className(element); break;}
			case linktext:		{byElement = By.linkText(element); break;}
			case paritallinktext:	{byElement = By.partialLinkText(element); break;}
			case tagname:		{byElement = By.tagName(element); break;}
			default:		{throw new Exception();}
		}
		WebElement query = driver.findElement(byElement);
		
		return query;	
	}
	
	//a method to obtain screenshots
	public void takeScreenshot(String action) throws IOException {
		//make our screenshot name friendly
		action = action.replaceAll("[^a-zA-Z0-9]", "");  
	
		//take a screenshot
		File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
		
		//save the screenshot to a file
		FileUtils.copyFile(scrFile, new File("target/" + System.currentTimeMillis() + action + ".png"));    	
	}
}
